home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / NET / PKT_SCHE.{1P < prev    next >
Text File  |  1999-09-17  |  11KB  |  406 lines

  1. #ifndef __NET_PKT_SCHED_H
  2. #define __NET_PKT_SCHED_H
  3.  
  4. #define PSCHED_GETTIMEOFDAY    1
  5. #define PSCHED_JIFFIES         2
  6. #define PSCHED_CPU         3
  7.  
  8. #define PSCHED_CLOCK_SOURCE    PSCHED_JIFFIES
  9.  
  10. #include <linux/pkt_sched.h>
  11. #include <net/pkt_cls.h>
  12.  
  13. struct rtattr;
  14. struct Qdisc;
  15.  
  16. struct qdisc_walker
  17. {
  18.     int    stop;
  19.     int    skip;
  20.     int    count;
  21.     int    (*fn)(struct Qdisc *, unsigned long cl, struct qdisc_walker *);
  22. };
  23.  
  24. struct Qdisc_class_ops
  25. {
  26.     /* Child qdisc manipulation */
  27.     int            (*graft)(struct Qdisc *, unsigned long cl, struct Qdisc *, struct Qdisc **);
  28.     struct Qdisc *        (*leaf)(struct Qdisc *, unsigned long cl);
  29.  
  30.     /* Class manipulation routines */
  31.     unsigned long        (*get)(struct Qdisc *, u32 classid);
  32.     void            (*put)(struct Qdisc *, unsigned long);
  33.     int            (*change)(struct Qdisc *, u32, u32, struct rtattr **, unsigned long *);
  34.     int            (*delete)(struct Qdisc *, unsigned long);
  35.     void            (*walk)(struct Qdisc *, struct qdisc_walker * arg);
  36.  
  37.     /* Filter manipulation */
  38.     struct tcf_proto **    (*tcf_chain)(struct Qdisc *, unsigned long);
  39.     unsigned long        (*bind_tcf)(struct Qdisc *, unsigned long, u32 classid);
  40.     void            (*unbind_tcf)(struct Qdisc *, unsigned long);
  41.  
  42.     /* rtnetlink specific */
  43.     int            (*dump)(struct Qdisc *, unsigned long, struct sk_buff *skb, struct tcmsg*);
  44. };
  45.  
  46. struct Qdisc_ops
  47. {
  48.     struct Qdisc_ops    *next;
  49.     struct Qdisc_class_ops    *cl_ops;
  50.     char            id[IFNAMSIZ];
  51.     int            priv_size;
  52.  
  53.     int             (*enqueue)(struct sk_buff *, struct Qdisc *);
  54.     struct sk_buff *    (*dequeue)(struct Qdisc *);
  55.     int             (*requeue)(struct sk_buff *, struct Qdisc *);
  56.     int            (*drop)(struct Qdisc *);
  57.  
  58.     int            (*init)(struct Qdisc *, struct rtattr *arg);
  59.     void            (*reset)(struct Qdisc *);
  60.     void            (*destroy)(struct Qdisc *);
  61.     int            (*change)(struct Qdisc *, struct rtattr *arg);
  62.  
  63.     int            (*dump)(struct Qdisc *, struct sk_buff *);
  64. };
  65.  
  66. struct Qdisc_head
  67. {
  68.     struct Qdisc_head *forw;
  69. };
  70.  
  71. extern struct Qdisc_head qdisc_head;
  72.  
  73. struct Qdisc
  74. {
  75.     struct Qdisc_head    h;
  76.     int             (*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
  77.     struct sk_buff *    (*dequeue)(struct Qdisc *dev);
  78.     unsigned        flags;
  79. #define TCQ_F_BUILTIN    1
  80. #define TCQ_F_THROTTLED    2
  81.     struct Qdisc_ops    *ops;
  82.     struct Qdisc        *next;
  83.     u32            handle;
  84.     atomic_t        refcnt;
  85.     struct sk_buff_head    q;
  86.     struct device         *dev;
  87.  
  88.     struct tc_stats        stats;
  89.     unsigned long        tx_timeo;
  90.     unsigned long        tx_last;
  91.     int            (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q);
  92.  
  93.     /* This field is deprecated, but it is still used by CBQ
  94.      * and it will live until better solution will be invented.
  95.      */
  96.     struct Qdisc        *__parent;
  97.  
  98.     char            data[0];
  99. };
  100.  
  101. struct qdisc_rate_table
  102. {
  103.     struct tc_ratespec rate;
  104.     u32        data[256];
  105.     struct qdisc_rate_table *next;
  106.     int        refcnt;
  107. };
  108.  
  109.  
  110. /* 
  111.    Timer resolution MUST BE < 10% of min_schedulable_packet_size/bandwidth
  112.    
  113.    Normal IP packet size ~ 512byte, hence:
  114.  
  115.    0.5Kbyte/1Mbyte/sec = 0.5msec, so that we need 50usec timer for
  116.    10Mbit ethernet.
  117.  
  118.    10msec resolution -> <50Kbit/sec.
  119.    
  120.    The result: [34]86 is not good choice for QoS router :-(
  121.  
  122.    The things are not so bad, because we may use artifical
  123.    clock evaluated by integration of network data flow
  124.    in the most critical places.
  125.  
  126.    Note: we do not use fastgettimeofday.
  127.    The reason is that, when it is not the same thing as
  128.    gettimeofday, it returns invalid timestamp, which is
  129.    not updated, when net_bh is active.
  130.  
  131.    So, use PSCHED_CLOCK_SOURCE = PSCHED_CPU on alpha and pentiums
  132.    with rtdsc. And PSCHED_JIFFIES on all other architectures, including [34]86
  133.    and pentiums without rtdsc.
  134.    You can use PSCHED_GETTIMEOFDAY on another architectures,
  135.    which have fast and precise clock source, but it is too expensive.
  136.  */
  137.  
  138. /* General note about internal clock.
  139.  
  140.    Any clock source returns time intervals, measured in units
  141.    close to 1usec. With source PSCHED_GETTIMEOFDAY it is precisely
  142.    microseconds, otherwise something close but different chosen to minimize
  143.    arithmetic cost. Ratio usec/internal untis in form nominator/denominator
  144.    may be read from /proc/net/psched.
  145.  */
  146.  
  147.  
  148. #if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY
  149.  
  150. typedef struct timeval    psched_time_t;
  151. typedef long        psched_tdiff_t;
  152.  
  153. #define PSCHED_GET_TIME(stamp) do_gettimeofday(&(stamp))
  154. #define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ))
  155.  
  156. #define PSCHED_EXPORTLIST EXPORT_SYMBOL(psched_tod_diff);
  157.  
  158. #else /* PSCHED_CLOCK_SOURCE != PSCHED_GETTIMEOFDAY */
  159.  
  160. #define PSCHED_EXPORTLIST PSCHED_EXPORTLIST_1 PSCHED_EXPORTLIST_2
  161.  
  162. typedef u64    psched_time_t;
  163. typedef long    psched_tdiff_t;
  164.  
  165. extern psched_time_t    psched_time_base;
  166.  
  167. #if PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES
  168.  
  169. #if HZ == 100
  170. #define PSCHED_JSCALE 13
  171. #elif HZ == 1024
  172. #define PSCHED_JSCALE 10
  173. #else
  174. #define PSCHED_JSCALE 0
  175. #endif
  176.  
  177. #define PSCHED_EXPORTLIST_2
  178.  
  179. #if ~0UL == 0xFFFFFFFF
  180.  
  181. #define PSCHED_WATCHER unsigned long
  182.  
  183. extern PSCHED_WATCHER psched_time_mark;
  184.  
  185. #define PSCHED_GET_TIME(stamp) ((stamp) = psched_time_base + (((unsigned long)(jiffies-psched_time_mark))<<PSCHED_JSCALE))
  186.  
  187. #define PSCHED_EXPORTLIST_1 EXPORT_SYMBOL(psched_time_base); \
  188.                             EXPORT_SYMBOL(psched_time_mark);
  189.  
  190. #else
  191.  
  192. #define PSCHED_GET_TIME(stamp) ((stamp) = (jiffies<<PSCHED_JSCALE))
  193.  
  194. #define PSCHED_EXPORTLIST_1 
  195.  
  196. #endif
  197.  
  198. #define PSCHED_US2JIFFIE(delay) (((delay)+(1<<PSCHED_JSCALE)-1)>>PSCHED_JSCALE)
  199.  
  200. #elif PSCHED_CLOCK_SOURCE == PSCHED_CPU
  201.  
  202. extern psched_tdiff_t psched_clock_per_hz;
  203. extern int psched_clock_scale;
  204.  
  205. #define PSCHED_EXPORTLIST_2 EXPORT_SYMBOL(psched_clock_per_hz); \
  206.                             EXPORT_SYMBOL(psched_clock_scale);
  207.  
  208. #define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz)
  209.  
  210. #if CPU == 586 || CPU == 686
  211.  
  212. #define PSCHED_GET_TIME(stamp) \
  213. ({ u64 __cur; \
  214.    __asm__ __volatile__ (".byte 0x0f,0x31" :"=A" (__cur)); \
  215.    (stamp) = __cur>>psched_clock_scale; \
  216. })
  217.  
  218. #elif defined (__alpha__)
  219.  
  220. #define PSCHED_WATCHER u32
  221.  
  222. extern PSCHED_WATCHER psched_time_mark;
  223.  
  224. #define PSCHED_GET_TIME(stamp) \
  225. ({ u32 __res; \
  226.    __asm__ __volatile__ ("rpcc %0" : "r="(__res)); \
  227.    if (__res <= psched_time_mark) psched_time_base += 0x100000000UL; \
  228.    psched_time_mark = __res; \
  229.    (stamp) = (psched_time_base + __res)>>psched_clock_scale; \
  230. })
  231.  
  232. #define PSCHED_EXPORTLIST_1 EXPORT_SYMBOL(psched_time_base); \
  233.                             EXPORT_SYMBOL(psched_time_mark);
  234.  
  235. #else
  236.  
  237. #error PSCHED_CLOCK_SOURCE=PSCHED_CPU is not supported on this arch.
  238.  
  239. #endif /* ARCH */
  240.  
  241. #endif /* PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES */
  242.  
  243. #endif /* PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY */
  244.  
  245. #if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY
  246. #define PSCHED_TDIFF(tv1, tv2) \
  247. ({ \
  248.        int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; \
  249.        int __delta = (tv1).tv_usec - (tv2).tv_usec; \
  250.        if (__delta_sec) { \
  251.                switch (__delta_sec) { \
  252.            default: \
  253.                __delta = 0; \
  254.            case 2: \
  255.                __delta += 1000000; \
  256.            case 1: \
  257.                __delta += 1000000; \
  258.                } \
  259.        } \
  260.        __delta; \
  261. })
  262.  
  263. extern int psched_tod_diff(int delta_sec, int bound);
  264.  
  265. #define PSCHED_TDIFF_SAFE(tv1, tv2, bound, guard) \
  266. ({ \
  267.        int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; \
  268.        int __delta = (tv1).tv_usec - (tv2).tv_usec; \
  269.        switch (__delta_sec) { \
  270.        default: \
  271.            __delta = psched_tod_diff(__delta_sec, bound); guard; break; \
  272.        case 2: \
  273.            __delta += 1000000; \
  274.        case 1: \
  275.            __delta += 1000000; \
  276.        case 0: ; \
  277.        } \
  278.        __delta; \
  279. })
  280.  
  281. #define PSCHED_TLESS(tv1, tv2) (((tv1).tv_usec < (tv2).tv_usec && \
  282.                 (tv1).tv_sec <= (tv2).tv_sec) || \
  283.                  (tv1).tv_sec < (tv2).tv_sec)
  284.  
  285. #define PSCHED_TADD2(tv, delta, tv_res) \
  286. ({ \
  287.        int __delta = (tv).tv_usec + (delta); \
  288.        (tv_res).tv_sec = (tv).tv_sec; \
  289.        if (__delta > 1000000) { (tv_res).tv_sec++; __delta -= 1000000; } \
  290.        (tv_res).tv_usec = __delta; \
  291. })
  292.  
  293. #define PSCHED_TADD(tv, delta) \
  294. ({ \
  295.        (tv).tv_usec += (delta); \
  296.        if ((tv).tv_usec > 1000000) { (tv).tv_sec++; \
  297.          (tv).tv_usec -= 1000000; } \
  298. })
  299.  
  300. /* Set/check that time is in the "past perfect";
  301.    it depends on concrete representation of system time
  302.  */
  303.  
  304. #define PSCHED_SET_PASTPERFECT(t)    ((t).tv_sec = 0)
  305. #define PSCHED_IS_PASTPERFECT(t)    ((t).tv_sec == 0)
  306.  
  307. #define    PSCHED_AUDIT_TDIFF(t) ({ if ((t) > 2000000) (t) = 2000000; })
  308.  
  309. #else
  310.  
  311. #define PSCHED_TDIFF(tv1, tv2) (long)((tv1) - (tv2))
  312. #define PSCHED_TDIFF_SAFE(tv1, tv2, bound, guard) \
  313. ({ \
  314.        long __delta = (tv1) - (tv2); \
  315.        if ( __delta > (bound)) {  __delta = (bound); guard; } \
  316.        __delta; \
  317. })
  318.  
  319.  
  320. #define PSCHED_TLESS(tv1, tv2) ((tv1) < (tv2))
  321. #define PSCHED_TADD2(tv, delta, tv_res) ((tv_res) = (tv) + (delta))
  322. #define PSCHED_TADD(tv, delta) ((tv) += (delta))
  323. #define PSCHED_SET_PASTPERFECT(t)    ((t) = 0)
  324. #define PSCHED_IS_PASTPERFECT(t)    ((t) == 0)
  325. #define    PSCHED_AUDIT_TDIFF(t)
  326.  
  327. #endif
  328.  
  329. struct tcf_police
  330. {
  331.     struct tcf_police *next;
  332.     int        refcnt;
  333.     u32        index;
  334.  
  335.     int        action;
  336.     int        result;
  337.     u32        ewma_rate;
  338.     u32        burst;
  339.     u32        mtu;
  340.  
  341.     u32        toks;
  342.     u32        ptoks;
  343.     psched_time_t    t_c;
  344.     struct qdisc_rate_table *R_tab;
  345.     struct qdisc_rate_table *P_tab;
  346.  
  347.     struct tc_stats    stats;
  348. };
  349.  
  350. extern void tcf_police_destroy(struct tcf_police *p);
  351. extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est);
  352. extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p);
  353. extern int tcf_police(struct sk_buff *skb, struct tcf_police *p);
  354.  
  355. extern __inline__ void tcf_police_release(struct tcf_police *p)
  356. {
  357.     if (p && --p->refcnt == 0)
  358.         tcf_police_destroy(p);
  359. }
  360.  
  361. extern struct Qdisc noop_qdisc;
  362. extern struct Qdisc_ops noop_qdisc_ops;
  363. extern struct Qdisc_ops pfifo_qdisc_ops;
  364. extern struct Qdisc_ops bfifo_qdisc_ops;
  365.  
  366. int register_qdisc(struct Qdisc_ops *qops);
  367. int unregister_qdisc(struct Qdisc_ops *qops);
  368. struct Qdisc *qdisc_lookup(struct device *dev, u32 handle);
  369. struct Qdisc *qdisc_lookup_class(struct device *dev, u32 handle);
  370. void dev_init_scheduler(struct device *dev);
  371. void dev_shutdown(struct device *dev);
  372. void dev_activate(struct device *dev);
  373. void dev_deactivate(struct device *dev);
  374. void qdisc_reset(struct Qdisc *qdisc);
  375. void qdisc_destroy(struct Qdisc *qdisc);
  376. struct Qdisc * qdisc_create_dflt(struct device *dev, struct Qdisc_ops *ops);
  377. int qdisc_new_estimator(struct tc_stats *stats, struct rtattr *opt);
  378. void qdisc_kill_estimator(struct tc_stats *stats);
  379. struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct rtattr *tab);
  380. void qdisc_put_rtab(struct qdisc_rate_table *tab);
  381. int teql_init(void);
  382. int tc_filter_init(void);
  383. int pktsched_init(void);
  384.  
  385. void qdisc_run_queues(void);
  386. int qdisc_restart(struct device *dev);
  387.  
  388. extern __inline__ void qdisc_wakeup(struct device *dev)
  389. {
  390.     if (!dev->tbusy) {
  391.         struct Qdisc *q = dev->qdisc;
  392.         if (qdisc_restart(dev) && q->h.forw == NULL) {
  393.             q->h.forw = qdisc_head.forw;
  394.             qdisc_head.forw = &q->h;
  395.         }
  396.     }
  397. }
  398.  
  399. extern __inline__ unsigned psched_mtu(struct device *dev)
  400. {
  401.     unsigned mtu = dev->mtu;
  402.     return dev->hard_header ? mtu + dev->hard_header_len : mtu;
  403. }
  404.  
  405. #endif
  406.